#include "ResourceManager.h"
#include "graphics/object/Skybox.h"

uint32_t ResourceManager::m_WindowWidth = 800;
uint32_t ResourceManager::m_WindowHeight = 600;
std::vector<VKShader*> ResourceManager::m_Shaders;
std::vector<Object*> ResourceManager::m_Objects;
std::unordered_map<std::string, Texture*> ResourceManager::m_Textures;

VKShader* ResourceManager::LoadShader(const std::string& vertFilePath, const std::string& fragFilePath)
{
	VKShader* tmpShader = new VKShader(vertFilePath, fragFilePath);
	return tmpShader;
}

Model* ResourceManager::LoadModel(const std::string& filePath)
{
	Model* tmpModel = new Model(filePath);
	return tmpModel;
}

void ResourceManager::ReadResource(const std::string& resourceFilePath)
{
	std::ifstream file(resourceFilePath, std::ios::in);
	if (!file.is_open())
		SDL_Log("failed to open resource file");

	std::string line;
	while (!file.eof())
	{
		getline(file, line);
		if (line == "#Shaders")
		{
			std::string shaderDir = "resources/shaders/";
			while (getline(file, line))
			{
				if (line[0] == '#' || line.empty())
					break;
				else
				{
					std::string vertPath = shaderDir + line;
					getline(file, line);
					std::string fragPath = shaderDir + line;
					m_Shaders.emplace_back(LoadShader(vertPath, fragPath));
				}
			}
		}
		if (line == "#Skyboxes")
		{
			std::vector<std::string> filePaths;
			while (getline(file, line))
			{
				if (line[0] == '#' || line.empty())
					break;
				else
				{
					std::string tmpPath = "resources/skyboxes/" + line;
					filePaths.push_back(tmpPath);
				}
			}
			Object* skybox = new Skybox(filePaths);
			m_Objects.emplace_back(skybox);
		}
		if (line == "#Models")
		{

			while (getline(file, line))
			{
				if (line[0] == '#' || line.empty())
					break;
				else
				{
					std::string objectPath = "resources/models/" + line.substr(0, line.find_first_of(':'));
					m_Objects.emplace_back(LoadModel(objectPath));
				}
			}
		}

	}
}

void ResourceManager::ClearResource()
{
	for (const auto& object : m_Objects)
		delete object;

	for (const auto& text : m_Textures)
		delete text.second;
	m_Textures.clear();

	for (const auto& shader : ResourceManager::m_Shaders)
		delete shader;
}

VKShader* ResourceManager::FindShader(const std::string& shaderName)
{
	std::string tmpName = "resources/shaders/" + shaderName;
	for (auto shader : m_Shaders)
	{
		if (strcmp(shader->m_ShaderName.data(), tmpName.data()) == 0)
		{
			return shader;
		}
	}

	SDL_Log("Cannot find shader:%s,return the first available shader!", shaderName.c_str());
	return m_Shaders[0];
}

Object* ResourceManager::FindObject(const std::string& objectName)
{
	for (auto object : m_Objects)
	{
		if (strcmp(object->m_ObjectName.c_str(), object->m_ObjectName.c_str()) == 0)
		{
			return object;
		}
	}
	return nullptr;
}

Texture* ResourceManager::FindTexture(const std::string& texturePath, aiTextureType textureType)
{
	auto it = m_Textures.find(texturePath);
	if (it != m_Textures.end())
		return (*it).second;
	else
	{
		Texture* tex = new Texture(texturePath,textureType);
		tex->m_TextureName = texturePath;
		m_Textures.emplace(texturePath,tex);
		return tex;
	}
}

